/**
 * Copyright (c) 2010
 * Bert Young. UESTC. 
 */

#include "TCPTask.h"

int TCPTask::uniqueid = 0; // test, consider for unique id creator

TCPTask::TCPTask(int localfd, const struct sockaddr_in * client, bool buffer) : socket(localfd, client), heartbeatTimer(60 * 1000L)
{
	this->buffered = buffer;
	this->state = idle;
	this->disconnect = disconnect_none;
	//this->verified = false;
	this->beatSent = false;
	this->id = ++uniqueid; // bert test
#ifndef CHINESE
	debug("New task id: %d, fd = %d", this->id, localfd );
#else
	debug("新连接id: %d, 描述符 = %d", this->id, localfd );
#endif
}

bool TCPTask::checkHeartbeat(const Time & now)
{
	if ( heartbeatTimer(now) )
	{	// 在listenrecv中，收到测试指令就清beatSent
		if ( beatSent )
		{
#ifndef CHINESE
			debug("error heart stop!");
#else
			debug("客户端挂了？心跳停止了！");
#endif
			return false;// should abort this task
		}
		else
		{
			ServerTestCmd test;
			if ( this->socket.sendPacket(&test, sizeof(ServerTestCmd)) )
			{
#ifndef CHINESE
				debug("Test to client!!!");
#else
				debug("试探客户端");
#endif
				beatSent = true;
			}
		}
	}
	return true;
}

void TCPTask::nextState()
{
	ConnectionState oldstate = this->state;
	switch(oldstate)
	{
		case idle:
			this->state = verify;
			break;
		case verify:
			this->buffered = true;//so the timeticker sendcmd will put msg into sendBuf
			//addToContainer();
			this->state = okay;
			break;
		case okay:
			//removeFromContainer();
			this->state = recycle;
			this->buffered = false;
			break;
		case recycle:
			this->state = idle;
			break;
	}
}

bool TCPTask::sendPacket( const void * cmd, unsigned int len)
{	// the timeticker thread will call this
	debug("%s = send length %d, %.*s",__PRETTY_FUNCTION__, len, len, (char *)cmd);
	return this->socket.sendPacket(cmd, len, this->buffered);
}

bool TCPTask::recv(bool needRecv )
{	// OKAY thread call this function
	int nBytes = 0;
	if ( needRecv )//epoll_wait success, just ::recv
		nBytes = this->socket.recv();
	if ( nBytes < 0 )
	{
		debug("recv error : %d", nBytes);
		return false;
	}

	unsigned char cmd[SocketConnection::MAX_DATASIZE];
	while ( true )// 将应用缓冲的消息取干净
	{
		nBytes = this->socket.recvPacketNoPoll(cmd);

		if ( nBytes > 0 )
		{
			debug("%s = recv length %d, %.*s",__PRETTY_FUNCTION__, nBytes, nBytes, (char *)cmd);
			NullBaseCmd * pCmd = (NullBaseCmd *)cmd;
#if 1
			if ( pCmd->byCmd == NULL_CMD )
			{
				if ( pCmd->byParam == SERVER_TEST_PARAM )
				{
#ifndef CHINESE
					debug("Return from client!!!");
#else
					debug("客户端说它还活着");
#endif
					this->beatSent = false;
				}
				else if ( pCmd->byParam == CLIENT_TEST_PARAM )
				{
					ClientTestCmd testclient;
					if ( this->sendPacket(&testclient, sizeof(ClientTestCmd)) )
#ifndef CHINESE
						debug("echo client success!!!");
#else
						debug("成功响应客户端");
#endif
					else
					{
#ifndef CHINESE
						debug("echo client failed !!!");
#else
						debug("!失败响应客户端");
#endif
						return false;
					}
				}
				else
				{
					debug("Invalid cmd, expect test cmd !!!");
					return false;// wrong cmd;
				}
			}
			else
#endif
			{
				// add to msgqueue, or msgparse it
				parse( pCmd, nBytes );
			}
		}
		else
		{
			return true;
		}
	}
	return true;
}

bool TCPTask::send()//OKAY thread call me
{
	return this->socket.sync();
}

void TCPTaskNoBuffer::parse(const void * cmd, unsigned int len)
{
	msgParse(cmd, len);
}

void TCPTaskBuffer::parse(const void * cmd, unsigned int len)
{
	MsgBuffer::put(cmd, len);
}

